#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Copyright (c) 2011 - 2013 Stefano Mazzucco <stefano -at- curso.re>
# All rights reserved.
#
# This file is part of Crystal Ball Plus.
#
# Crystal Ball Plus is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Crystal Ball Plus is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Crystal Ball Plus.  If not, see <http://www.gnu.org/licenses/>.

"""Functions that generate text reports for the d-spacing and angle matches.

"""
import sys
import os

from datetime import date as _date

from fileio import nl, newname
from utilities import genrow

import numpy as np

def gen_d_report(dic, out, nomatch=True, just='r'):
    """Generate a report on angle match from dictionary of dictionaries 'dic'
    and save it to file 'out'.

    *Parameters*

    dic : dictionary of dictionaries
          usually, the output of 'compare_d'

    out : file object, e.g. use sys.stdout

    nomatch : bool (optional)
              whether the files with no matches should be listed in the report
              default is True

    just : string (optional)
           justification; can be either of 'r', 'l', 'c' (right, left, center)
           default is 'r'

    *See also*

    compare_d

    """

    # change below if you want to change the header:
    headtuple = ('SPOT NO.', 'MEAS. SPACING', 'REF. SPACING',
                 '%ERROR', ' MILLER PLANE')
    sep = '    '                # four spaces are better than one tab
    head = ''
    for i in headtuple:
        head += i + sep
    head = head.rstrip()
    head += nl

    # today_machine = _date.today().isoformat() # 2011-05-13
    today_user = _date.today().strftime('%b %d %Y') # May 13 2011
    out.write('    D-SPACING MATCH REPORT GENERATED ON %s    '.center(80, '#')
            % today_user)
    out.write(2 * nl)
    inplist = dic.keys()[:]
    inplist.sort()
    reflist = []
    for i in inplist:
        j = dic[i].keys()[:]
        j.sort
        reflist.append(j)
    for i, inpfile in enumerate(inplist):
        for reffile in reflist[i]:
            subdic = dic[inpfile][reffile]
            msg = 'INPUT FILE: ' + str(inpfile) + nl
            msg += len(msg) * ' '
            msg += ' REFERENCE FILE: ' + str(reffile) + nl
            if subdic is not None:
                arr = subdic[0]
                inpobj = subdic[1]
                refobj = subdic[2]
                msg += 'STRUCTURE: ' + refobj.chemname + ' ('
                msg += refobj.structure + '); '
                msg += 'SPACE GROUP: ' + refobj.sg_name + ' ('
                msg += repr(refobj.sg_number) +');' + nl
                msg += 'CRYSTAL SYSTEM: ' + refobj.crystsys + 2 * nl
                msg += head
                out.write(msg)
                for val in xrange(arr.size):
                    inp_idx = arr[val]['inp_idx']
                    inp_d = inpobj.d_spacings[inp_idx]
                    inp_d_s = '%.3f' % inp_d
                    ref_idx = arr[val]['ref_idx']
                    ref_d = refobj.d_spacings[ref_idx]
                    ref_d_s = '%.3f' % ref_d
                    percerr = arr[val]['err'] * 100
                    percerr_s = '%.3f' % percerr
                    plane = refobj.hkl[ref_idx]
                    plane_s = str(plane).lstrip(plane.__class__.__name__)
                    inprow = [str(inp_idx + 1),  # start from 1
                              inp_d_s, ref_d_s,
                              percerr_s, plane_s]
                    dataline = genrow(inprow, headtuple, sep, just=just)
                    dataline = dataline.rstrip(sep)
                    dataline += nl
                    out.write(dataline)
                out.write(80 * '-' + 2 * nl)
            else:
                if nomatch:
                    msg += 'NO MATCHES' + 2 * nl
                    out.write(msg)
                    out.write(80 * '-' + 2 * nl)
    out.write(80 * '_' + nl)
    out.flush()

def gen_angle_report(dic, out, nomatch=True, just='r'):
    """Generate a report on angle match from dictionary of dictionaries 'dic'
    and save it to file 'out'.

    *Parameters*

    dic : dictionary of dictionaries
          usually, the output of 'compare_angles'

    out : file object, e.g. use sys.stdout

    nomatch : bool (optional)
              whether the files with no matches should be listed in the report
              default is True

    just : string (optional)
           justification; can be either of 'r', 'l', 'c' (right, left, center)
           default is 'r'

    *See also*

    compare_angles

    """

    # change below if you want to change the header:
    headtuple = ('1ST SPOT', '2ND SPOT', '    1ST PLANE', '    2ND PLANE',
                 'MEAS. ANGLE', 'REF. ANGLE', '%ERROR', 'ZONE AXIS')
    sep = '    '                # four spaces are better than one tab
    head = ''
    for i in headtuple:
        head += i + sep
    head = head.rstrip()
    head += nl

    # today_machine = _date.today().isoformat() # 2011-05-13
    today_user = _date.today().strftime('%b %d %Y') # May 13 2011
    out.write('    ANGLE MATCH REPORT GENERATED ON %s    '.center(80, '#')
            % today_user)
    out.write(2 * nl)
    inplist = dic.keys()[:]
    inplist.sort()
    reflist = []
    for i in inplist:
        j = dic[i].keys()[:]
        j.sort()
        reflist.append(j)
    for i, inpfile in enumerate(inplist):
        for reffile in reflist[i]:
            subdic = dic[inpfile][reffile]
            msg = 'INPUT FILE: ' + str(inpfile) + nl
            msg += len(msg) * ' '
            msg += ' REFERENCE FILE: ' + str(reffile) + nl
            if subdic is not None:
                grp = subdic[0]
                grp_keys = grp.keys()[:] # copy if you want to sort!
                grp_keys.sort()
                refobj = subdic[2]
                msg += 'STRUCTURE: ' + refobj.chemname + ' ('
                msg += refobj.structure + '); '
                msg += 'SPACE GROUP: ' + refobj.sg_name + ' ('
                msg += repr(refobj.sg_number) +')' + nl
                msg += 'CRYSTAL SYSTEM: ' + refobj.crystsys + 2 * nl
                msg += head
                out.write(msg)
                for group in grp_keys:
                    mtc_s = 'MATCH_' + str(group)
                    out.write(len(mtc_s) * '=' + nl + mtc_s + 2 * nl)
                    for val in grp[group]:
                        inp_ang = val['inp_ang']
                        inp_ang_s = '%.3f' % inp_ang
                        ref_ang = val['ref_ang']
                        ref_ang_s = '%.3f' % ref_ang
                        percerr = val['err'] * 100
                        percerr_s = '%.3f' % percerr
                        spot_0 = val['spot_0']
                        plane_0 = val['hkl_0']
                        plane_0_s = str(plane_0).lstrip(
                            plane_0.__class__.__name__)
                        spot_1 = val['spot_1']
                        plane_1 = val['hkl_1']
                        plane_1_s = str(plane_1).lstrip(
                            plane_1.__class__.__name__)
                        za = val['zone_axis']
                        za_s = str(za)
                        inprow = [str(spot_0 + 1), # start from 1
                                  str(spot_1 + 1), # start from 1
                                  plane_0_s, plane_1_s,
                                  inp_ang_s, ref_ang_s,
                                  percerr_s, za_s]
                        dataline = genrow(inprow, headtuple, sep, just=just)
                        dataline = dataline.rstrip(sep)
                        dataline += nl
                        out.write(dataline)
                out.write(80 * '-' + 2 * nl)
            else:
                if nomatch:
                    msg += 'NO MATCHES' + 2 * nl
                    out.write(msg)
                    out.write(nl)
                    out.write(80 * '-' + 2 * nl)
    out.write(80 * '_' + nl)
    out.flush()
